{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**问题：**\n",
    "假设你正在为一个电影推荐系统设计一个简单的KNN算法。我们有以下一些用户的电影评分数据，数据由两个特征组成：用户对电影A和电影B的评分，分别在1-5之间。用户的标签（电影类型偏好）是动作片（标签0）或者是喜剧片（标签1）。我们有一个新用户，他给电影A评分为3，电影B评分为4。请问这个用户可能偏好哪种类型的电影？\n",
    "\n",
    "**数据：**\n",
    "\n",
    "| 用户   | 电影A评分 | 电影B评分 | 偏好类型 |\n",
    "| ------ | --------- | --------- | -------- |\n",
    "| 用户1  | 5         | 1         | 动作片   |\n",
    "| 用户2  | 4         | 2         | 动作片   |\n",
    "| 用户3  | 2         | 5         | 喜剧片   |\n",
    "| 用户4  | 1         | 4         | 喜剧片   |\n",
    "| 用户5  | 3         | 2         | 动作片   |\n",
    "| 用户6  | 2         | 5         | 喜剧片   |\n",
    "\n",
    "你需要做以下步骤：\n",
    "1. 构造数据\n",
    "2. 创建KNN模型\n",
    "3. 使用数据训练模型\n",
    "4. 预测新用户的喜好"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 0. 引入核心包"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.neighbors import KNeighborsClassifier"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. X, y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = np.array([[1, 2], [2, 3], [3, 1], [4, 5], [5, 4], [3, 5]])#TODO\n",
    "\n",
    "y = np.array([0, 0, 0, 1, 1, 1])#TODO  # 0表示动作片，1表示喜剧片"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. 创建 KNN 模型\n",
    "k = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "knn = KNeighborsClassifier(n_neighbors=1)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3. 训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-1 {\n",
       "  /* Definition of color scheme common for light and dark mode */\n",
       "  --sklearn-color-text: black;\n",
       "  --sklearn-color-line: gray;\n",
       "  /* Definition of color scheme for unfitted estimators */\n",
       "  --sklearn-color-unfitted-level-0: #fff5e6;\n",
       "  --sklearn-color-unfitted-level-1: #f6e4d2;\n",
       "  --sklearn-color-unfitted-level-2: #ffe0b3;\n",
       "  --sklearn-color-unfitted-level-3: chocolate;\n",
       "  /* Definition of color scheme for fitted estimators */\n",
       "  --sklearn-color-fitted-level-0: #f0f8ff;\n",
       "  --sklearn-color-fitted-level-1: #d4ebff;\n",
       "  --sklearn-color-fitted-level-2: #b3dbfd;\n",
       "  --sklearn-color-fitted-level-3: cornflowerblue;\n",
       "\n",
       "  /* Specific color for light theme */\n",
       "  --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
       "  --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-icon: #696969;\n",
       "\n",
       "  @media (prefers-color-scheme: dark) {\n",
       "    /* Redefinition of color scheme for dark theme */\n",
       "    --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
       "    --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-icon: #878787;\n",
       "  }\n",
       "}\n",
       "\n",
       "#sk-container-id-1 {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 pre {\n",
       "  padding: 0;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-hidden--visually {\n",
       "  border: 0;\n",
       "  clip: rect(1px 1px 1px 1px);\n",
       "  clip: rect(1px, 1px, 1px, 1px);\n",
       "  height: 1px;\n",
       "  margin: -1px;\n",
       "  overflow: hidden;\n",
       "  padding: 0;\n",
       "  position: absolute;\n",
       "  width: 1px;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-dashed-wrapped {\n",
       "  border: 1px dashed var(--sklearn-color-line);\n",
       "  margin: 0 0.4em 0.5em 0.4em;\n",
       "  box-sizing: border-box;\n",
       "  padding-bottom: 0.4em;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-container {\n",
       "  /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "     but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "     so we also need the `!important` here to be able to override the\n",
       "     default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "     See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "  display: inline-block !important;\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-text-repr-fallback {\n",
       "  display: none;\n",
       "}\n",
       "\n",
       "div.sk-parallel-item,\n",
       "div.sk-serial,\n",
       "div.sk-item {\n",
       "  /* draw centered vertical line to link estimators */\n",
       "  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "  background-size: 2px 100%;\n",
       "  background-repeat: no-repeat;\n",
       "  background-position: center center;\n",
       "}\n",
       "\n",
       "/* Parallel-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item::after {\n",
       "  content: \"\";\n",
       "  width: 100%;\n",
       "  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "  flex-grow: 1;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel {\n",
       "  display: flex;\n",
       "  align-items: stretch;\n",
       "  justify-content: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:first-child::after {\n",
       "  align-self: flex-end;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:last-child::after {\n",
       "  align-self: flex-start;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:only-child::after {\n",
       "  width: 0;\n",
       "}\n",
       "\n",
       "/* Serial-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-serial {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "  align-items: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  padding-right: 1em;\n",
       "  padding-left: 1em;\n",
       "}\n",
       "\n",
       "\n",
       "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "clickable and can be expanded/collapsed.\n",
       "- Pipeline and ColumnTransformer use this feature and define the default style\n",
       "- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "*/\n",
       "\n",
       "/* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable {\n",
       "  /* Default theme specific background. It is overwritten whether we have a\n",
       "  specific estimator or a Pipeline/ColumnTransformer */\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "/* Toggleable label */\n",
       "#sk-container-id-1 label.sk-toggleable__label {\n",
       "  cursor: pointer;\n",
       "  display: block;\n",
       "  width: 100%;\n",
       "  margin-bottom: 0;\n",
       "  padding: 0.5em;\n",
       "  box-sizing: border-box;\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:before {\n",
       "  /* Arrow on the left of the label */\n",
       "  content: \"▸\";\n",
       "  float: left;\n",
       "  margin-right: 0.25em;\n",
       "  color: var(--sklearn-color-icon);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "/* Toggleable content - dropdown */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content {\n",
       "  max-height: 0;\n",
       "  max-width: 0;\n",
       "  overflow: hidden;\n",
       "  text-align: left;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content pre {\n",
       "  margin: 0.2em;\n",
       "  border-radius: 0.25em;\n",
       "  color: var(--sklearn-color-text);\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted pre {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "  /* Expand drop-down */\n",
       "  max-height: 200px;\n",
       "  max-width: 100%;\n",
       "  overflow: auto;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "  content: \"▾\";\n",
       "}\n",
       "\n",
       "/* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator-specific style */\n",
       "\n",
       "/* Colorize estimator box */\n",
       "#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label label.sk-toggleable__label,\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  /* The background is the default theme color */\n",
       "  color: var(--sklearn-color-text-on-default-background);\n",
       "}\n",
       "\n",
       "/* On hover, darken the color of the background */\n",
       "#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "/* Label box, darken color on hover, fitted */\n",
       "#sk-container-id-1 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator label */\n",
       "\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  font-family: monospace;\n",
       "  font-weight: bold;\n",
       "  display: inline-block;\n",
       "  line-height: 1.2em;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label-container {\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "/* Estimator-specific */\n",
       "#sk-container-id-1 div.sk-estimator {\n",
       "  font-family: monospace;\n",
       "  border: 1px dotted var(--sklearn-color-border-box);\n",
       "  border-radius: 0.25em;\n",
       "  box-sizing: border-box;\n",
       "  margin-bottom: 0.5em;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "/* on hover */\n",
       "#sk-container-id-1 div.sk-estimator:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
       "\n",
       "/* Common style for \"i\" and \"?\" */\n",
       "\n",
       ".sk-estimator-doc-link,\n",
       "a:link.sk-estimator-doc-link,\n",
       "a:visited.sk-estimator-doc-link {\n",
       "  float: right;\n",
       "  font-size: smaller;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1em;\n",
       "  height: 1em;\n",
       "  width: 1em;\n",
       "  text-decoration: none !important;\n",
       "  margin-left: 1ex;\n",
       "  /* unfitted */\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted,\n",
       "a:link.sk-estimator-doc-link.fitted,\n",
       "a:visited.sk-estimator-doc-link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "/* Span, style for the box shown on hovering the info icon */\n",
       ".sk-estimator-doc-link span {\n",
       "  display: none;\n",
       "  z-index: 9999;\n",
       "  position: relative;\n",
       "  font-weight: normal;\n",
       "  right: .2ex;\n",
       "  padding: .5ex;\n",
       "  margin: .5ex;\n",
       "  width: min-content;\n",
       "  min-width: 20ex;\n",
       "  max-width: 50ex;\n",
       "  color: var(--sklearn-color-text);\n",
       "  box-shadow: 2pt 2pt 4pt #999;\n",
       "  /* unfitted */\n",
       "  background: var(--sklearn-color-unfitted-level-0);\n",
       "  border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted span {\n",
       "  /* fitted */\n",
       "  background: var(--sklearn-color-fitted-level-0);\n",
       "  border: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link:hover span {\n",
       "  display: block;\n",
       "}\n",
       "\n",
       "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link {\n",
       "  float: right;\n",
       "  font-size: 1rem;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1rem;\n",
       "  height: 1rem;\n",
       "  width: 1rem;\n",
       "  text-decoration: none;\n",
       "  /* unfitted */\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "#sk-container-id-1 a.estimator_doc_link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>KNeighborsClassifier(n_neighbors=1)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" checked><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;&nbsp;KNeighborsClassifier<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.5/modules/generated/sklearn.neighbors.KNeighborsClassifier.html\">?<span>Documentation for KNeighborsClassifier</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>KNeighborsClassifier(n_neighbors=1)</pre></div> </div></div></div></div>"
      ],
      "text/plain": [
       "KNeighborsClassifier(n_neighbors=1)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knn.fit(X, y)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4. 用模型推理(预测)用户的喜好"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "new_user = np.array([[3, 4]])   \n",
    "prediction = knn.predict(new_user)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 5. 数据可视化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Predicted preference: 1\n"
     ]
    },
    {
     "data": {
      "image/png": "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DWPFihVMnTqV3377jbFjx7J161aGDh3qqBRExIFCQkLYtGkdzZsHAH0s7SZTM7y9P+K118bw/vu6x01J1qNHD77+ehlBQbuBFri51f7fknZUrvwry5Yt4/7773dkiHILcejhs+wnFf/111/cdttt3HXXXVZPKj569KjVQwBbt25NbGwso0eP5pVXXqF27dosW7aM+vXrOyoFEXGwWrVqsWnTen7dtAlatwZg6tS3ierTx24nY0rRuu++++jatSvLly9nx44dwNWHtnbr1g1XV9cbrC1SdBxaFN3oScUJCQk52nr27EnPnj3tFJGIlFYNmzQhq0sXzpw5Q/Qjj+CeyxWsUnK5urryz3/+k06dOhEXF0eXLl1UEEmxK1EnWouIFJqXF5lff83muDi66nJ8ESmEEnWitYiIiIijqCgSERERQYfPRMRZXLyIW0AA3TIzMU6dgnLlHB2RiJQyKopExGmY0tJwI/spWiIittHhMxERERFUFImIiIgAKopEREREABVFIiIiIoCKIhERERFAV5+JiLNwcSHrH//g3F9/UdZFv++JiO1UFImIc/D2JnPVKjbExdHV29vR0YhIKaRfp0RERERQUSQiIiIC6PCZiDiLixdxq16dzpcvw5EjesyHiNhMRZGIOA3T2bN4osd8iEjh6PCZiIiICCqKRERERAAVRSIiIiKAiiIRERERQEWRiIiICKCrz0TEWbi4kNW0KcnJyfjqMR8iUggqikTEOXh7k7lpE2v1mA8RKST9OiUiIiKCiiIRERERQIfPRMRZpKXhVrcukWlpsG8flC3r6IhEpJRRUSQizsEwMB05gg9gNgxHRyMipZAOn4mIiIigokhEREQEUFEkIiIiAqgoEhEREQFKUFE0efJkTCYTw4cPz7NPTEwMJpPJ6uXl5VV8QYqIiIjTKhFXn23ZsoWZM2fSsGHDG/b19/fn999/t7w3mUz2DE1ESguTCSMsjAupqXjr3wURKQSH7ylKTU2lT58+zJo1i/Lly9+wv8lkIjAw0PK6/fbbiyFKESnxfHy48ssv/PT+++Dj4+hoRKQUcvieoiFDhtCtWzfuvfdeXn/99Rv2T01NJSQkhKysLMLDw3njjTeoV69env0zMjLIyMiwvE9JSQHAbDZjNptvPoFrZI9X1OOWFM6eHzh/jsqv9HP2HJVf6WevHIvjMzMZhuPucrZg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RGzh4+PDnLlzmfjGGyxcuJA///wTgF9//ZWaNWs6ODoRESlOBS6K7HE58o2eFp6QkJCjrWfPnvTs2bPIY5FbW2BgIM888wxms5m4uDiqVavm6JBERKSY6dlnIiIiIqgoEhEREQFUFImIiIgAKopEREREgEIWRVeuXGHVqlXMnDmTCxcuAHDy5ElSU1OLNDgRERGR4mLTfYoAjhw5QufOnTl69CgZGRlERkbi5+fHm2++SUZGBh9//LE94hQRERGxK5v3FA0bNoxmzZpx/vx5vP/3JHGA+++/P8fdpkVERERKC5v3FK1bt46NGzfi4eFh1V69enVOnDhRZIGJiIiIFCeb9xRlZWXl+uDX48eP4+fnVyRBiYiIiBQ3m4uijh078u6771rem0wmUlNTee211+jatWtRxiYiIiJSbGw+fDZ16lQ6depE3bp1uXTpEr1792bfvn1UqlSJL774wh4xioiIiNidzUVR1apV+eWXX1iwYAG//vorqampDBw4kD59+lideC0iIiJSmthcFAG4ubnxyCOPFHUsIiIiIg5ToKLom2++oUuXLri7u/PNN9/k27d79+5FEpiIiIhIcSpQURQVFcWpU6cICAggKioqz34mkynXK9NERERESroCFUVZWVm5/l1ERETEWdh8Sf6xY8fsEYeIiIiIQ9lcFFWvXp22bdsya9Yszp8/b4+YRERERIqdzUXR1q1badGiBePHj6dy5cpERUWxaNEiMjIy7BGfiIiISLGwuShq0qQJU6ZM4ejRoyxfvpzbbruNxx9/nNtvv50BAwbYI0YRERERu7O5KMpmMplo3749s2bNYtWqVdSoUYNPP/20KGMTERERKTaFLoqOHz/OW2+9RePGjWnRogW+vr58+OGHRRmbiIiISLGx+Y7WM2fOJDY2lg0bNhAaGkqfPn34+uuvCQkJsUd8IiIiIsXC5qLo9ddfJzo6mvfee49GjRrZIyYRERGRYmdzUXT06FFMJpM9YhERERFxGJuLIpPJxN9//82cOXPYu3cvAHXr1mXgwIGULVu2yAMUERERKQ6Fuk9RzZo1mTZtGufOnePcuXNMmzaNmjVrsn37dnvEKCIiImJ3Nu8peu655+jevTuzZs3Cze3q6leuXGHQoEEMHz6ctWvXFnmQIiIiIvZmc1G0detWq4IIwM3NjZEjR9KsWbMiDU5ERESkuNh8+Mzf35+jR4/maD927Bh+fn5FEpSIiIhIcbO5KOrVqxcDBw7kyy+/5NixYxw7dowFCxYwaNAgoqOj7RGjiIiIiN3ZXBS9/fbbPPDAA/Tt25fq1atTvXp1+vfvz0MPPcSbb75p01iTJk2iefPm+Pn5ERAQQFRUFL///nu+68TExGAymaxeXl5etqYhIiIiYsXmc4o8PDyYPn06kyZN4sCBAwDUrFkTHx8fmze+Zs0ahgwZQvPmzbly5QqvvPIKHTt2ZM+ePZQpUybP9fz9/a2KJ903SURERG6WzUVRNh8fHxo0aHBTG1+xYoXV+5iYGAICAti2bRv/+Mc/8lzPZDIRGBh4U9sWERERuVaBi6IBAwYUqN/cuXMLHUxycjIAFSpUyLdfamoqISEhZGVlER4ezhtvvEG9evVy7ZuRkUFGRoblfUpKCgBmsxmz2VzoWHOTPV5Rj1tSOHt+4Pw5Kr/Sz9lzVH6ln71yLI7PzGQYhlGQji4uLoSEhNCkSRPyW2Xp0qWFCiQrK4vu3bvz999/s379+jz7bdq0iX379tGwYUOSk5N5++23Wbt2Lbt376Zq1ao5+o8dO5Zx48blaI+NjS3UIT8REREpfmlpafTu3Zvk5GT8/f3tso0CF0VDhgzhiy++ICQkhMcee4xHHnnkhnt0bPHUU0+xfPly1q9fn2txkxez2UxYWBjR0dFMmDAhx/Lc9hQFBwdz9uzZIv9QzWYz8fHxREZG4u7uXqRjlwTOnh84f47Kr/Rz9hyVX+lnrxxTUlKoVKmSXYuiAh8++/DDD3nnnXdYsmQJc+fOZdSoUXTr1o2BAwfSsWPHmzrZeejQoXz33XesXbvWpoIIwN3dnSZNmrB///5cl3t6euLp6Znrevb6gbTn2CWBs+cHzp+j8iv9nD1H5Vf6FXWOxfF52XRJvqenJ9HR0cTHx7Nnzx7q1avH008/TfXq1UlNTbV544ZhMHToUJYuXcqPP/5IjRo1bB4jMzOTnTt3UrlyZZvXFREREclW6KvPXFxcMJlMGIZBZmZmocYYMmQIsbGxfP311/j5+XHq1CkAypYti7e3NwB9+/alSpUqTJo0CYDx48fTqlUratWqxd9//82UKVM4cuQIgwYNKmwqIiIiIrbtKcrIyOCLL74gMjKSO++8k507d/LBBx9w9OhRfH19bd74jBkzSE5Opl27dlSuXNny+vLLLy19jh49SlJSkuX9+fPnGTx4MGFhYXTt2pWUlBQ2btxI3bp1bd6+iIiISLYC7yl6+umnWbBgAcHBwQwYMIAvvviCSpUq3dTGC3KOd0JCgtX7adOmMW3atJvaroiIiMj1ClwUffzxx1SrVo077riDNWvWsGbNmlz7LVmypMiCExERESkuBS6K+vbtq8dpiIiIiNMqcFEUExNjxzBEREREHMumE61FREREnJWKIhERERFUFImIiIgAKopEREREABVFIiIiIoCKIhERERFARZGIiIgIoKJIREREBFBRJCIiIgKoKBIREREBVBSJiIiIACqKRERERAAVRSIiIiKAiiK7+euvvwgICODw4cPFvu1WrVqxePHiYt+uiIhIaaaiyE4mTpxIjx49qF69uqXt2WefpWnTpnh6etK4ceNCjTtr1izuvvtuypcvT/ny5bn33nv573//a9Vn9OjRvPzyy2RlZd1EBiIiIrcWFUV2kJaWxpw5cxg4cGCOZQMGDKBXr16FHjshIYHo6Gh++uknNm3aRHBwMB07duTEiROWPl26dOHChQssX7680NsRERG51bg5OgBntHz5cjw9PWnVqpVV+3vvvQfAn3/+ya+//lqosefPn2/1fvbs2SxevJjVq1fTt29fAFxdXenatSsLFiygW7duhdqOiIjIrUZ7iuxgw4YNNG3atFi2lZaWhtlspkKFClbtLVq0YN26dcUSg4iIiDNQUWQHR44cISgoqFi29dJLLxEUFMS9995r1R4UFMSxY8d0XpGIiEgB6fCZHVy6dAkvLy+7b2fy5MksWLCAhISEHNvz9vYmKyuLjIwMvL297R6LiIhIaaeiyA4qVqzI+fPn7bqNt99+m8mTJ7Nq1SoaNmyYY/m5c+coU6aMCiIREZEC0uEzO2jcuDF79uyx2/hvvfUWEyZMYMWKFTRr1izXPrt27aJJkyZ2i0FERMTZqCiyg8jISHbv3p1jb9H+/ftJTEzk1KlTpKenk5iYSGJiIpcvXy7w2G+++Savvvoqc+fOpXr16pw6dYpTp06Rmppq1W/dunV07NixSPIRERG5FagosoMGDRoQHh7OV199ZdU+aNAgmjRpwsyZM/njjz9o0qQJTZo04eTJk5Y+JpOJmJiYPMeeMWMGly9f5qGHHqJy5cqW19tvv23pc+LECTZu3Mhjjz1W5LmJiIg4K51TZCdjxoxhxIgRDB48GBeXq7VnQkJCvuscOnQINzc32rRpk2efgjw25L333qN///5UrVrVlpBFRERuaSqK7KRbt27s27ePEydOEBwcXKB14uLiePzxx6ldu/ZNbTsgIIDnn3/+psYQERG51agoKgKHDh1izpw5HDx4kF69evHZZ5/xr3/9i+HDh9s0zpAhQ4oknhdeeKFIxhEREbmV6Jyim3DlyhWefuopatasyQeTJ3P+m28AeGboUKpWrszXX3/t4AhFRESkoBxaFE2aNInmzZvj5+dHQEAAUVFR/P777zdcb+HChYSGhuLl5UWDBg2Ii4srhmhzevKJJ5g1cybTDIOTmZl887+7R/8CtLtwgQcfeID4+HiHxCYiIiK2cWhRtGbNGoYMGcLPP/9MfHw8ZrOZjh07cvHixTzX2bhxI9HR0QwcOJAdO3YQFRVFVFQUu3btKsbI4ddff2XO3Ll8YBgMA3yuWRYCfGUY3G0YvDBsGIZhFGtsIiIiYjuHFkUrVqygf//+1KtXj0aNGhETE8PRo0fZtm1bnutMnz6dzp07M2LECMLCwpgwYQLh4eF88MEHxRg5fPLJJ1R2c2NAHsvdgFGGwc69e9m0aVNxhiYiIiKFUKJOtE5OTgbI8cT3a23atCnHlVWdOnVi2bJlufbPyMggIyPD8j4lJQUAs9mM2WwudKy/7dpFR3d3cHcnexTz/x6pkf1nW6AMV+8u3bx580Jvq6TI/rxu5nMr6Zw9R+VX+jl7jsqv9LNXjsXxmZmMEnJsJysri+7du/P333+zfv36PPt5eHjw6aefEh0dbWn76KOPGDduHKdPn87Rf+zYsYwbNy5He2xsLD4+PjnaRUREpORJS0ujd+/eJCcn4+/vb5dtlJg9RUOGDGHXrl35FkSFMWrUKKs9SykpKQQHB9OxY8eb+lDHjx/PJ+++yx+ZmZbzicze3sTPnUvkgAG4p6ezFOgP/Pzzz4SFhd1MGiWC2WwmPj6eyMhI3N3dHR2OXTh7jsqv9HP2HJVf6WevHLOP9NhTiSiKhg4dynfffcfatWtveBfmwMDAHHuETp8+TWBgYK79PT098fT0zNHu7u5+U5M1aNAg3pg4kbcNgwnXj52eTkZ6Oq+7utKsZctcn2Jfmt3sZ1caOHuOyq/0c/YclV/pV9Q5Fsfn5dATrQ3DYOjQoSxdupQff/yRGjVq3HCdiIgIVq9ebdUWHx9PRESEvcLMVUhICOMnTOB14Elg/zXLVgFtXV057OnJBzNmFGtcIiIiUjgOLYqGDBnC559/TmxsLH5+fpYnvqenp1v69O3bl1GjRlneDxs2jBUrVjB16lR+++03xo4dy9atWxk6dGixx//KK68wffp0FpYtS20g7H9V7INAVlgYa9avd7q9RCIiIs7KoUXRjBkzSE5Opl27dlZPfP/yyy8tfY4ePUpSUpLlfevWrYmNjeWTTz6hUaNGLFq0iGXLllG/fv1ij99kMvHss89yPCmJzz//nEeeew6AH374ge2//kqTJk2KPSYREREpHIeeU1SQC99ye7J8z5496dmzpx0iKhxvb2/69OmD2WwmLi6Oli1bYjKZHB2WiIiI2EDPPhMRERFBRZGIiIgIoKJIREREBFBRJCIiIgKoKBIREREBVBSJiIiIACqKRERERAAVRSIiIiKAiiIRERERQEWRiIiICKCiSERERARQUSQiIiICqCgSERERAVQUiYiIiAAqikREREQAFUUiIiIigIoiEREREUBFkYiIiAigokhEREQEUFEkIiIiAqgoEhEREQFUFImIiIgAKopEREREABVFIiIiIoCKIhERERFARZGIiIgIoKJIREREBFBRJCIiIgKoKBIREREBVBSJiIiIACqKRERERAAHF0Vr167lvvvuIygoCJPJxLJly/Ltn5CQgMlkyvE6depU8QQsIiIiTsuhRdHFixdp1KgRH374oU3r/f777yQlJVleAQEBdopQREREbhVujtx4ly5d6NKli83rBQQEUK5cuaIPSERERG5ZDi2KCqtx48ZkZGRQv359xo4dS5s2bfLsm5GRQUZGhuV9SkoKAGazGbPZXKRxZY9X1OOWFM6eHzh/jsqv9HP2HJVf6WevHIvjMzMZhmHYfSsFYDKZWLp0KVFRUXn2+f3330lISKBZs2ZkZGQwe/ZsPvvsMzZv3kx4eHiu64wdO5Zx48blaI+NjcXHx6eowhcRERE7SktLo3fv3iQnJ+Pv72+XbZSqoig3bdu2pVq1anz22We5Ls9tT1FwcDBnz54t8g/VbDYTHx9PZGQk7u7uRTp2SeDs+YHz56j8Sj9nz1H5lX72yjElJYVKlSrZtSgqlYfPrtWiRQvWr1+f53JPT088PT1ztLu7u9vtB9KeY5cEzp4fOH+Oyq/0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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.title(\"User Movie Preference\", size=15)   \n",
    "plt.xlabel(\"Movie A rating\")  \n",
    "plt.ylabel(\"Movie B rating\")  \n",
    "plt.grid(True)  \n",
    "  \n",
    "# 绘制原始样本点，不同的影片喜好类别用不同的颜色标记  \n",
    "colors = ['red' if label == 0 else 'blue' for label in y]  \n",
    "plt.scatter(X[:, 0], X[:, 1], c=colors, s=50, edgecolor='k')  \n",
    "  \n",
    "# 绘制新数据点，用红色x标记，大小为8  \n",
    "plt.plot(new_user[:, 0], new_user[:, 1], 'ro', markersize=8)  \n",
    "  \n",
    "# 新数据最近邻索引为第一个最近邻的索引  \n",
    "dist, idx = knn.kneighbors(new_user, n_neighbors=1, return_distance=True)  \n",
    "nearest = X[idx.flatten()]  # 获取最近邻点的坐标  \n",
    "  \n",
    "# 用红线标记新数据点与最近邻点的连接线  \n",
    "nearest_x = nearest[:, 0]  \n",
    "nearest_y = nearest[:, 1]  \n",
    "plt.plot([new_user[0, 0], nearest_x[0]], [new_user[0, 1], nearest_y[0]], 'r--')  \n",
    "  \n",
    "# 为每个点添加坐标文本  \n",
    "for x, y in zip(X[:, 0], X[:, 1]):  \n",
    "    plt.text(x, y+0.1, f'({x}, {y})', fontsize=10)  \n",
    "  \n",
    "# 为新数据点添加坐标文本  \n",
    "plt.text(new_user[0, 0], new_user[0, 1]+0.1, f'({new_user[0, 0]}, {new_user[0, 1]})', fontsize=10)  \n",
    "  \n",
    "# 显示预测结果  \n",
    "print(f\"Predicted preference: {prediction[0]}\")  # 0 for action, 1 for comedy   \n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
